<?php

declare(strict_types=1);

/**
 * Copyright (C), 2021-2021, Shall Buy Life info. Co., Ltd.
 * FileName: functions.php
 * Description: 工具函数.
 *
 * @author lwl
 * @Create Date    2021/6/11 13:33
 * @Update Date    2021/6/11 13:33 By lwl
 *
 * @version v1.0
 */

use Example\Constants\CodeMessageConstant;
use Illuminate\Http\Response;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use itbdw\Ip\IpLocation;
use Carbon\Carbon;

/*
 * by:lwl
 * 获取ip地址
 */
if (!function_exists('getRealIp')) {
    function getRealIp($ip = '',$type = 'string')
    {
        $ips = IpLocation::getLocation($ip);

        switch ($type) {
            case 'string':
                $ip = $ips['country'] . $ips['province'] . $ips['city'] . $ips['ip'];

                break;

            case 'json':
                $ip = json_encode($ips);

                break;

            default:
                $ip = $ips;

                break;
        }

        return $ip;
    }
}

/*
 * by:lwl
 * 随机数
 */
if (!function_exists('uuid')) {
    function uuid()
    {
        return (string)Str::uuid();
    }
}

/**
 *  by:lwl
 *  数组 转 树形结构
 */
if (!function_exists('listToTree')) {
    function listToTree($list, $pk = 'id', $pid = 'parent_id', $children = 'children', $root = 0)
    {
        $tree = $refer = [];
        if (is_array($list)) {
            foreach ($list as $key => $value) {
                $refer[$value[$pk]] =& $list[$key];
            }
            foreach ($list as $key => $value) {
                $parentId = $value[$pid];
                if ($root == $parentId) {
                    $tree[] =& $list[$key];
                } else {
                    if (!empty($refer[$parentId])) {
                        $parent =& $refer[$parentId];
                        $parent[$children][] =& $list[$key];
                    }
                }
            }
        }
        return $tree;
    }
}

/*
 * by:lwl
 * 无限极分类查找某个节点下的所有 子类
 * model:模型类 例如:Cate::class
 * id:最高父类节点
 * isSelf:true:数组返回自己，false:数组不返回自己
 * data：返回数组
 */
if (!function_exists('getAllNextId')) {
    function getAllNextId($model, $id, $isSelf = false, $data = []): array
    {
        if (!$model instanceof $model) { //new 一个对象
            $model = new $model();
        }
        $parentIds = $model->query()->where('parent_id', $id)->pluck('id');
        if (count($parentIds) > 0) {
            foreach ($parentIds as $parentId) {
                if ($isSelf) array_push($data, $id);
                $data[] = $parentId;
                $data = getAllNextId($model, $parentId, $isSelf, $data);
            }
        } else {
            if ($isSelf) array_push($data, $id);
        }
        return array_unique($data);
    }
}

/**
 * 查找上级所有节点
 * by:lwl
 */
if (!function_exists('getTopParentId')) {
    {
        function getTopParentId($data, $id)
        {
            $array = array();
            foreach ($data as $value) {
                if ($value['id'] == $id) {
                    $array[] = $value['id'];
                    $array = array_merge(getTopParentId($data, $value['parent_id']), $array);
                }
            }
            return $array;
        }
    }
}

/**
 * 数组 降维
 * $data 数组
 * $column 子类字段 数组
 * by:lwl
 */
if (!function_exists('arrayReduction')) {
    {
        function arrayReduction($data, $column)
        {
            $result = [];
            $data = array_values(array_filter(Arr::pluck($data, $column)));
            foreach ($data as $values) {
                foreach ($values as $item) {
                    array_push($result, $item);
                }
            }
            return $result;
        }
    }
}

/**
 * 是否有html
 * by:lwl
 */
if (!function_exists('judgeHtml')) {
    function judgeHtml($str): bool
    {
        return $str != strip_tags($str);
    }
}


/**
 * 获取富文本编译器中的内容
 * @param string $contentStr :提取的文本
 * @param string $type :提取数据类型:img,video,audio
 * @return array
 * by:lwl
 */
if (!function_exists('getRichTextContent')) {
    function getRichTextContent($contentStr = '', $type = 'img'): array
    {
        $return = [];
        $patternTag = '/<' . $type . '\b.*?(?:\>|\/>)/i';
        preg_match_all($patternTag, $contentStr, $match);
        if (isset($match[0])) {
            foreach ($match[0] as $item) {
                $patternSrc = '/\bsrc\b\s*=\s*[\'\"]?([^\'\"]*)[\'\"]?/i';
                preg_match_all($patternSrc, $item, $matchContent);
                if (isset($matchContent[1])) {
                    foreach ($matchContent[1] as $content) {
                        $return[] = $content;
                    }
                }
            }
        }
        return $return;
    }
}

/**
 * 将文本 根据指定的长度 拆分为数组
 * @param string $str :文本
 * @param int $size :长度
 * @return array
 * by:lwl
 */
if (!function_exists('splitCharacter')) {
    function splitCharacter($str, $size = 200): array
    {
        return mb_str_split($str, $size, mb_detect_encoding($str));
    }
}

/**
 * FunctionName：millisecond
 * Description：获得毫秒
 * Author：zmy
 * @return float
 */
if (!function_exists('millisecond')) {
    function millisecond(): int
    {
        return intval(microtime(true) * 10000);
//        list($msec, $sec) = explode(' ', microtime());
//        return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    }
}

/**
 * FunctionName：exceptionLog
 * Description：错误日志
 * Author：lwl
 * @param $exception
 * @param $request
 */
if (!function_exists('exceptionLog')) {
    function exceptionLog($exception = '', $request)
    {
        if (!$exception instanceof Exception) {
            $exception = new Exception();
        }
        $code = $exception->getCode();
        if ($code != Response::HTTP_OK) {
            $logInstance = Log::channel('exception');
            $logInstance->info(PHP_EOL);
            $logInstance->info('---------------------------------------- 响应 START ------------------------------');
            $logInstance->info('请求唯一标识：' . uuid());
            $logInstance->info('请求状态码：' . $code);
            $logInstance->info('请求地址：' . $request->getPathInfo());
            $logInstance->info('请求头：' . json_encode($request->header()));
            $logInstance->info('请求参数：' . json_encode($request->all()));
            $logInstance->info('错误提示：' . $exception->getMessage());
            $logInstance->info('---------------------------------------- 响应 END ---------------------------------');
        }
        die("ERROR: 请查看  /storage/logs/exception-" . date('Y-m-d') . ".log");
    }
}

/**
 * FunctionName：taskLog
 * Description：计划任务日志
 * Author：lwl
 */
if (!function_exists('taskLog')) {
    function taskLog()
    {
        $logInstance = Log::channel('task_success');
        $logInstance->info(PHP_EOL);
        $logInstance->info('---------------------------------------- Task Response START ------------------------------');
        $logInstance->info('请求唯一标识：' . uuid());
        $logInstance->info('请求状态码：' . Response::HTTP_OK);
        $logInstance->info('请求地址：' . request()->getPathInfo());
        $logInstance->info('请求头：' . json_encode(request()->header()));
        $logInstance->info('请求参数：' . json_encode(request()->all()));
        $logInstance->info('执行时间：' . Carbon::now());
        $logInstance->info('响应时长：' . round(microtime(true) - START, 3) . '秒');
        $logInstance->info('---------------------------------------- Task Response END ---------------------------------');
    }
}

/**
 * FunctionName：getSign
 * Description：验签
 * Author：zmy
 * @param $privateKey
 * @param $time
 * @return string
 */
if (!function_exists('getSign')) {
    function getSign($privateKey, $time): string
    {
        $accessString = CodeMessageConstant::ACCESS_STRING;
        return md5(($accessString . $privateKey . $accessString . $time));
    }
}

/**
 * FunctionName：projectPath
 * Description：获取项目根目录
 * Author：lwl
 * @param $privateKey
 * @param $time
 * @return array
 */
if (!function_exists('projectPath')) {
    function projectPath(): array
    {
        $composerJson = json_decode(file_get_contents(app_path('../composer.json')), true);
        $project = $composerJson['autoload']['psr-4'];
        return [
            'project_path' => app_path('../' . array_values($project)[1]),
            'project' => array_keys($project)[1],
        ];
    }
}

/**
 * FunctionName：redis
 * Description：模仿 thinkphp 助手函数 redis
 * Author：lwl
 * @return string
 */
if (!function_exists('redis')) {
    function redis(): string
    {
        return \Illuminate\Support\Facades\Redis::class;
    }
}

/**
 * FunctionName：fail
 * Description：模仿 thinkphp 助手函数 fail
 * Author：lwl
 * @return array
 */
if (!function_exists('fail')) {
    function fail(array $array): array
    {
        throw \ExceptionFactory::business($array);
    }
}
